﻿using Blm.PgsqlDriver.Helpers;
using Blm.Utils.Extensions;
using Npgsql;
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Threading.Tasks;
using VisionCloud.Domain.DtoModel.Ms;
using VisionCloud.Utility.Helpers;

namespace VisionSurface.Service.Ms
{
    /// <summary>
    /// 算法模板服务
    /// </summary>
    public class AlgoTemplateService
    {
        /// <summary>
        /// 添加任务的算法配置项
        /// </summary>
        /// <param name="taskId"></param>
        /// <param name="templateId"></param>
        /// <returns></returns>
        public async ValueTask<int> AddTaskAlgoTempItem(Guid taskId, Guid templateId, Guid? projectId = null)
        {
            var templateList = await GetAlgorithmParamTemplateListAsync(projectId);
            var destTemp = templateList.Where(p => p.AlgorithmParamTemplateGuid == templateId).FirstOrDefault();
            if (destTemp != null)
            {
                string sql = @"select * from ""MsAlgorithmParamTemplateItem"" where ""AlgorithmParamTemplateGuid"" = @AlgorithmParamTemplateGuid;";
                NpgsqlParameter[] parameters = new[] { new NpgsqlParameter("AlgorithmParamTemplateGuid", templateId) };
                using DataSet dataSet = PgSqlHelper.ExecuteDataSet(sql, parameters);
                if (dataSet != null && dataSet.Tables.Count > 0)
                {
                    DataTable dt = dataSet.Tables[0];
                    if (!dt.Columns.Contains("TaskGuid"))
                    {
                        DataColumn dataColumn = new DataColumn("TaskGuid", typeof(Guid));
                        dataColumn.DefaultValue = taskId;
                        dt.Columns.Add(dataColumn);
                    }

                    foreach (DataRow dr in dt.Rows)
                    {
                        dr["AlgorithmParamItemGuid"] = Guid.NewGuid();
                    }
                    string where = $@" ""TaskGuid"" = '{taskId}' ";
                    return PostgreHelper.AddDataSetToDbTable("MsTaskAlgorithmParamItem", where, dt, new DataColumn[] { dt.Columns["AlgorithmParamItemGuid"] });
                }
            }

            return -1;
        }

        /// <summary>
        /// 获取模板列表
        /// </summary>
        /// <returns></returns>
        public async ValueTask<List<MsAlgoTempDto>> GetAlgorithmParamTemplateListAsync(Guid? projectId = null)
        {
            List<MsAlgoTempDto> listResult = new List<MsAlgoTempDto>();

            string sql = $@"select t.""AlgorithmParamTemplateGuid"",t.""TemplateName"",t.""TemplateType""
                            from ""MsAlgorithmParamTemplate"" t
                            where t.""AlgorithmParamTemplateGuid"" = '{Guid.Empty}' and t.""IsDeleted"" = FALSE ";
            if (projectId.HasValue)
            {
                sql += $@" union all select t1.""AlgorithmParamTemplateGuid"",t1.""TemplateName"",t1.""TemplateType""
                        from ""MsAlgorithmParamTemplate"" t1
                        join ""MsProjectAlgorithm"" t2 on t2.""AlgorithmId"" = t1.""AlgorithmParamTemplateGuid""
                        where t2.""ProjectId"" = '{projectId}' and t1.""IsDeleted"" = FALSE ";
            }

            listResult = await PgSqlHelper.QueryListAsync<MsAlgoTempDto>(sql);

            // 默认模板排在最前
            listResult.Sort((a, b) =>
            {
                if (a.TemplateName == "默认")
                {
                    return -1;
                }
                if (b.TemplateName == "默认")
                {
                    return 1;
                }

                return string.CompareOrdinal(a.TemplateName, b.TemplateName);
            });

            return listResult;
        }

        private async Task<List<MsAlgorithmParamTemplateItemDto>> GetTaskAlgorithmParamTemplateDetail(Guid taskId)
        {
            List<MsAlgorithmParamTemplateItemDto> listResult = new List<MsAlgorithmParamTemplateItemDto>();
            List<MsAlgoItemDto> list = new List<MsAlgoItemDto>();

            string sql = $@"select t0.""TemplateName"", t1.""AlgorithmParamItemGuid"",t1.""AlgorithmParamTemplateGuid"",t1.""MeasureType"",t1.""ItemGroup"",
                            t1.""ItemGroupImagePath"",t1.""ItemName"",t1.""ItemKey"",t1.""ItemValue"",t1.""ItemType"",t1.""ItemValueRange""
                            from ""MsAlgorithmParamTemplate"" t0
                            join ""MsTaskAlgorithmParamItem"" t1 on t1.""AlgorithmParamTemplateGuid"" = t0.""AlgorithmParamTemplateGuid""
                            where t0.""IsDeleted"" = FALSE and t1.""TaskGuid""=@taskId";

            PostgreHelper postgreHelper = new PostgreHelper();
            NpgsqlParameter[] parameters = new[] { new NpgsqlParameter("taskId", taskId) };
            using var ds = postgreHelper.ReadDataSet(sql, parameters);
            if (ds != null && ds.Tables.Count > 0 && ds.Tables[0].Rows.Count > 0)
            {
                foreach (DataRow dr in ds.Tables[0].Rows)
                {
                    MsAlgoItemDto msAlgoItemDto = new MsAlgoItemDto
                    {
                        AlgorithmParamItemGuid = dr["AlgorithmParamItemGuid"].ToGuid(),
                        AlgorithmParamTemplateGuid = dr["AlgorithmParamTemplateGuid"].ToGuid(),
                        MeasureType = dr["MeasureType"].ToString(),
                        TemplateName = dr["TemplateName"].ToString(),
                        ItemGroup = dr["ItemGroup"].ToString(),
                        ItemGroupImagePath = dr["ItemGroupImagePath"].ToString(),
                        ItemName = dr["ItemName"].ToString(),
                        ItemKey = dr["ItemKey"].ToString(),
                        ItemValue = dr["ItemValue"].ToString(),
                        ItemType = dr["ItemType"].ToString(),
                        ItemValueRange = dr["ItemValueRange"].ToString()
                    };

                    list.Add(msAlgoItemDto);
                }
            }

            if (list.Count > 0)
            {
                /*
                 * 1.先找出测量项
                 */

                //测量项分组
                var measureTypeList = list.Select(p => new MsAlgoTempItemDto { MeasureType = p.MeasureType, TemplateName = p.TemplateName }).Distinct(new MsAlgoTempItemDtoComparer()).ToList();

                foreach (var measureType in measureTypeList)
                {
                    MsAlgorithmParamTemplateItemDto msAlgorithmParamTemplateItemDto = new MsAlgorithmParamTemplateItemDto();
                    msAlgorithmParamTemplateItemDto.MeasureType = measureType.MeasureType;
                    msAlgorithmParamTemplateItemDto.TemplateName = measureType.TemplateName;
                    msAlgorithmParamTemplateItemDto.AlgorithmParamTemplateGuid = list[0].AlgorithmParamTemplateGuid;
                    msAlgorithmParamTemplateItemDto.AlgorithmGroups = new List<AlgorithmGroup>();

                    //测量项的配置项分组
                    var groupList = list.Where(p => p.MeasureType == measureType.MeasureType).Select(p1 => new MsItemGroupDto { ItemGroup = p1.ItemGroup }).Distinct(new MsItemGroupDtoComparer()).ToList();
                    foreach (var group in groupList)
                    {
                        AlgorithmGroup algorithmGroup = new AlgorithmGroup();
                        algorithmGroup.ItemGroup = group.ItemGroup;
                        string itemGroupImagePath = string.Empty;
                        var picList = list.Where(p => p.MeasureType == measureType.MeasureType && p.ItemGroup == group.ItemGroup).ToList();
                        itemGroupImagePath = picList[0].ItemGroupImagePath;
                        algorithmGroup.ItemGroupImagePath = itemGroupImagePath;
                        msAlgorithmParamTemplateItemDto.AlgorithmGroups.Add(algorithmGroup);

                        //配置项某个分组的明细
                        var items = list.Where(p => p.MeasureType == measureType.MeasureType && p.ItemGroup == group.ItemGroup).ToList();
                        algorithmGroup.ParamSettings = new List<ParamSetting>();
                        foreach (var item in items)
                        {
                            ParamSetting paramSetting = new ParamSetting
                            {
                                AlgorithmParamItemGuid = item.AlgorithmParamItemGuid,
                                ItemKey = item.ItemKey,
                                ItemName = item.ItemName,
                                ItemType = item.ItemType,
                                ItemValue = item.ItemValue,
                                ItemValueRange = item.ItemValueRange
                            };
                            algorithmGroup.ParamSettings.Add(paramSetting);
                        }
                    }

                    listResult.Add(msAlgorithmParamTemplateItemDto);
                }
            }
            return listResult;
        }

        /// <summary>
        /// 获取任务的项目模板配置
        /// </summary>
        public async Task<string> GetAlgorthmconfig(Guid taskId)
        {
            Dictionary<string, string> dicMeasureType = new Dictionary<string, string>
            {
                { "开间进深", "r-kaijianjinshen" },
                { "平整度", "r-pingzhengdu" },
                { "水平度", "r-shuipingdu" },
                { "楼板板底水平度", "r-shuipingdu" },
                { "方正性", "r-fangzhengxing" },
                { "垂直度", "r-chuizhidu" },
                { "阴阳角", "r-yinyang" },
                { "踢脚线", "r-tijiaoxianpingzhengdu" },
                { "门套线", "r-mentaoxian" }
            };
            List<Algorthmconfig> algorthmconfigs = new List<Algorthmconfig>();
            var temp = await GetTaskAlgorithmParamTemplateDetail(taskId);
            if (temp != null)
            {
                foreach (var el in temp)//测量项
                {
                    Algorthmconfig algorthmconfig = new Algorthmconfig();
                    if (dicMeasureType.ContainsKey(el.MeasureType))
                    {
                        algorthmconfig.code = dicMeasureType[el.MeasureType];
                    }
                    else
                    {
                        algorthmconfig.code = el.MeasureType;
                    }
                    algorthmconfig.value = new Dictionary<string, int>();
                    foreach (var group in el.AlgorithmGroups)//测量项分组
                    {
                        foreach (var item in group.ParamSettings)
                        {
                            if (!algorthmconfig.value.ContainsKey(item.ItemKey))
                            {
                                algorthmconfig.value.Add(item.ItemKey, item.ItemValue.ToInt32());
                            }
                        }
                    }
                    algorthmconfigs.Add(algorthmconfig);
                }
                return algorthmconfigs.ToJsonStr();
            }
            return string.Empty;
        }
    }

    #region Comparer

    internal class MsAlgoTempItemDtoComparer : IEqualityComparer<MsAlgoTempItemDto>
    {
        public bool Equals(MsAlgoTempItemDto x, MsAlgoTempItemDto y)
        {
            if (x == null || y == null)
            {
                return false;
            }

            return x.MeasureType == y.MeasureType && x.TemplateName == y.TemplateName;
        }

        public int GetHashCode(MsAlgoTempItemDto obj)
        {
            if (obj == null)
                return 0;
            return (obj.MeasureType + obj.TemplateName).GetHashCode();
        }
    }

    internal class MsItemGroupDtoComparer : IEqualityComparer<MsItemGroupDto>
    {
        public bool Equals(MsItemGroupDto x, MsItemGroupDto y)
        {
            if (x == null || y == null)
            {
                return false;
            }
            //if (x.ItemGroup == y.ItemGroup && x.ItemGroupImagePath == y.ItemGroupImagePath)
            return x.ItemGroup == y.ItemGroup;
        }

        public int GetHashCode(MsItemGroupDto obj)
        {
            if (obj == null)
                return 0;
            return (obj.ItemGroup).GetHashCode();
        }
    }

    #endregion Comparer
}